﻿namespace Azalea.ORMap
{
    public class SqlWhere : ISqlWhere
    {
        private readonly CommandBuilder _cmdBuilder;
        private readonly string _tableName;

        public SqlWhere(CommandBuilder cmdBuilder, string tableName)
        {
            _cmdBuilder = cmdBuilder;
            _tableName = tableName;

            _cmdBuilder._sqlBuilder.Append(" where");
        }

        #region ISqlWhere Members

        public ISqlWhere And()
        {
            _cmdBuilder._sqlBuilder.Append(" and");
            return this;
        }

        public ISqlWhere Or()
        {
            _cmdBuilder._sqlBuilder.Append(" or");
            return this;
        }

        public ISqlWhere LeftBrace()
        {
            _cmdBuilder._sqlBuilder.Append(" (");
            return this;
        }

        public ISqlWhere RightBrace()
        {
            _cmdBuilder._sqlBuilder.Append(")");
            return this;
        }

        public ISqlWhere IsNull(string field)
        {
            _cmdBuilder._sqlBuilder.Append(" ")
                .Append(_cmdBuilder.QuotingKeyword(field))
                .Append(" is null");
            return this;
        }

        public ISqlWhere IsNotNull(string field)
        {
            _cmdBuilder._sqlBuilder.Append(" ")
                .Append(_cmdBuilder.QuotingKeyword(field))
                .Append(" is not null");
            return this;
        }

        public ISqlWhere Equals(string field, object value)
        {
            if (value == null)
            {
                return IsNull(field);
            }

            AddCondition(field, "=", value);
            return this;
        }

        public ISqlWhere NotEquals(string field, object value)
        {
            if (value == null)
            {
                return IsNotNull(field);
            }

            AddCondition(field, "<>", value);

            return this;
        }

        public ISqlWhere Like(string field, object value)
        {
            AddCondition(field, " like ", value);

            return this;
        }

        public ISqlWhere NotLike(string field, object value)
        {
            AddCondition(field, " not like ", value);

            return this;
        }

        public ISqlWhere GreaterThan(string field, object value)
        {
            AddCondition(field, ">", value);

            return this;
        }

        public ISqlWhere GreaterThanOrEquals(string field, object value)
        {
            AddCondition(field, ">=", value);

            return this;
        }

        public ISqlWhere LessThan(string field, object value)
        {
            AddCondition(field, "<", value);

            return this;
        }

        public ISqlWhere LessThanOrEquals(string field, object value)
        {
            AddCondition(field, "<=", value);

            return this;
        }

        public ISqlWhere In(string field, params object[] value)
        {
            _cmdBuilder._sqlBuilder.Append(" ")
                .Append(_cmdBuilder.QuotingKeyword(field))
                .Append(" in (");
            bool commaNeeded = false;
            foreach (object v in value)
            {
                string parameterName = _cmdBuilder.AddParameter(_tableName, field, v, true);

                if (commaNeeded)
                {
                    _cmdBuilder._sqlBuilder.Append(",");
                }
                _cmdBuilder._sqlBuilder.Append(parameterName);
                commaNeeded = true;
            }
            _cmdBuilder._sqlBuilder.Append(")");

            return this;
        }

        public ICommandBuilder Done()
        {
            return _cmdBuilder;
        }

        #endregion

        #region private members

        private void AddCondition(string field, string sqlOperator, object value)
        {
            string parameterName = _cmdBuilder.AddParameter(_tableName, field, value, true);

            _cmdBuilder._sqlBuilder.Append(" ")
                .Append(_cmdBuilder.QuotingKeyword(field))
                .Append(sqlOperator)
                .Append(parameterName);
        }

        #endregion
    }
}